function DD (opts) {
  this.oBox = document.getElementById(opts.oBox);
  this.aLi = this.oBox.getElementsByClassName("drag-list");
  this.listFn = opts.listFn;
  this.data = opts.data;
  this.zIndex = 0;
  this.sign = 1;
  this._init();
}
DD.prototype._init = function () {
  this._initData();
  this._createAli();
}
DD.prototype._initData = function () {
  for (var i = 0; i < this.data.length; i++) {
    this.data[i]._sign = this.sign;
    this.sign++;
  }
}
DD.prototype._addData = function (left, top) {
  this.data.push({
    left: left,
    top: top,
    _sign: this.sign
  });
  this._createAli();
  this.sign++;
}
DD.prototype._createAli = function () {
  this.oBox.innerHTML = '';
  var oFragment = document.createDocumentFragment();
  for (var i = 0; i < this.data.length; i++) {
    var item = this.data[i];
    var oLi = document.createElement("div");
    oLi.innerHTML = '<span>sign:' + item._sign + '</span>';
    oLi.style.left = item.left + 'px';
    oLi.style.top = item.top + 'px';
    oLi.className = 'drag-list';
    oLi.setAttribute('sign', this.data[i]._sign);
    oLi.id = item.id;
    oFragment.appendChild(oLi);
  }
  this.oBox.appendChild(oFragment);
  var sref = this;
  for (var i = 0; i < this.aLi.length; i++) {
    var item = this.aLi[i];
    this._drag(item);
    item.onclick = function (ev) {
      var sign = Number($(this).attr('sign'));
      sref.listFn && sref.listFn(this, sref.data, sign);
    }
  }
}
DD.prototype._drag = function (obj, handle) {
  var handle = handle || obj;
  var sref = this;
  handle.onmousedown = function (event) {
    var event = event || window.event;
    var disX = event.clientX - this.offsetLeft;
    var disY = event.clientY - this.offsetTop;
    var oNear = null;
    sref.zIndex = sref.zIndex + 1;
    obj.style.zIndex = sref.zIndex;
    obj.style.transition = 'none';
    document.onmousemove = function (event) {
      var event = event || window.event;
      var iL = event.clientX - disX;
      var iT = event.clientY - disY;
      var maxL = obj.parentNode.clientWidth - obj.offsetWidth;
      var maxT = obj.parentNode.clientHeight - obj.offsetHeight;

      iL < 0 && (iL = 0);
      iT < 0 && (iT = 0);
      iL > maxL && (iL = maxL);
      iT > maxT && (iT = maxT);
      obj.style.left = iL + "px";
      obj.style.top = iT + "px";
      $(sref.aLi).removeClass("hig");

      oNear = sref.findNearest(obj);

      oNear && $(oNear).addClass('hig');

      return false
    }
    document.onmouseup = function () {
      document.onmousemove = null;
      document.onmouseup = null;
      if (oNear) {
        var oldSign = $(obj).attr('sign');
        var newSign = $(oNear).attr('sign');

        var oldLeft = 0;
        var oldTop = 0;
        var newLeft = 0;
        var newTop = 0;

        for (var i = 0; i < sref.data.length; i++) {
          if (sref.data[i]._sign == oldSign) {
            oldLeft = sref.data[i].left;
            oldTop = sref.data[i].top;
          }
          if (sref.data[i]._sign == newSign) {
            newLeft = sref.data[i].left;
            newTop = sref.data[i].top;
          }
        }

        for (var i = 0; i < sref.data.length; i++) {
          if (sref.data[i]._sign == oldSign) {
            sref.data[i].left = newLeft;
            sref.data[i].top = newTop;
            obj.style.transition = 'all .2s';
            obj.style.left = newLeft + 'px';
            obj.style.top = newTop + 'px';
          }
          if (sref.data[i]._sign == newSign) {
            sref.data[i].left = oldLeft;
            sref.data[i].top = oldTop;
            oNear.style.transition = 'all .2s';
            oNear.style.left = oldLeft + 'px';
            oNear.style.top = oldTop + 'px';
          }
        }
        $(oNear).removeClass("hig");
      } else {
        var left = parseInt($(obj).css('left'));
        var top = parseInt($(obj).css('top'));
        var objSign = $(obj).attr('sign');
        for (var i = 0; i < sref.data.length; i++) {
          if (objSign == sref.data[i]._sign) {
            sref.data[i].left = left;
            sref.data[i].top = top;
          }
        }
      }
    }
    return false;
  }
}

DD.prototype.getData = function () {
  return this.data;
}
//找出相遇点中最近的元素
DD.prototype.findNearest = function (obj) {
  var filterLi = [];
  var aDistance = [];
  var aLi = this.aLi;
  for (i = 0; i < aLi.length; i++)
    aLi[i] != obj && (isButt(obj, aLi[i]) && (aDistance.push(getDistance(obj, aLi[i])), filterLi.push(aLi[i])));
  var minNum = Number.MAX_VALUE;
  var minLi = null;
  for (i = 0; i < aDistance.length; i++)
    aDistance[i] < minNum && (minNum = aDistance[i], minLi = filterLi[i]);
  return minLi
}
//求两点之间的距离
function getDistance (obj1, obj2) {
  var a = (obj1.offsetLeft + obj1.offsetWidth / 2) - (obj2.offsetLeft + obj2.offsetWidth / 2);
  var b = (obj1.offsetTop + obj1.offsetHeight / 2) - (obj2.offsetTop + obj2.offsetHeight / 2);
  return Math.sqrt(a * a + b * b);
}
// 碰撞检测
function isButt (obj1, obj2) {
  var l1 = obj1.offsetLeft;
  var t1 = obj1.offsetTop;
  var r1 = obj1.offsetLeft + obj1.offsetWidth;
  var b1 = obj1.offsetTop + obj1.offsetHeight;

  var l2 = obj2.offsetLeft;
  var t2 = obj2.offsetTop;
  var r2 = obj2.offsetLeft + obj2.offsetWidth;
  var b2 = obj2.offsetTop + obj2.offsetHeight;

  return !(r1 < l2 || b1 < t2 || r2 < l1 || b2 < t1)
}